import type { RouteRecordRaw } from "vue-router";

import { defineStore } from 'pinia';
import { getToken, removeToken, setToken } from '../utils/token-utils';
// import type { UserInfoState } from './interface';
import { ElMessage } from 'element-plus'
import { staticRoutes, allAsyncRoutes, anyRoute } from '@/router/routes'
import userinfoApi, { type userinfoModel } from '@/api/userinfo'
import router from "@/router";

// filterRoutesHandler方法  ---  这个方法没写,需要我们自己写
// 功能: 筛选路由
// 参数:
//    参数一: 动态路由 - 动态路由就是需要筛选的路由
//    参数二: 用户信息返回的当前用户可以看到的菜单
// 返回值:
//    返回值是筛选完之后的路由数组
const filterRoutesHandler = (routes: RouteRecordRaw[], routesName: string[]) => {

  // 进入当前函数之后,拿着一级路由在筛选,筛选出来的结果也只是对一级路由进行的
  // 展示只要一级路由有，二级路由就都会展示
  let result = routes.filter(route => { // routes 是路由数组,route是每一个路由

    if (route.children) { // 如果当前路由有子路由,那么对子路由进行筛选,得到一个新的数组,重新赋值给 route.children
      route.children = filterRoutesHandler(route.children, routesName); // 递归调用
    }

    return routesName.includes(route.name as string); //判断用户数据返回的菜单权限是不是包含当前路由的name属性
  })

  return result;
}

// 动态注册路由
const addRoutes = (allRoutes: RouteRecordRaw[]) => {
  allRoutes.forEach(route => {
    router.addRoute(route); // 这个方法是 router.addRoute() 是vue-router提供的,目的就是为了动态注册路由
  })
}

interface UserInfoState {
  token: string,
  userinfo: userinfoModel,
  menuRoutes: RouteRecordRaw[]
}

const initUserinfo = (): userinfoModel => ({
  avatar: '',
  name: '',
  buttons: [],
  roles: [],
  routes: []
})
/**
 * 用户信息
 * @methods setUserInfos 设置用户信息
 */
export const useUserInfoStore = defineStore('userInfo', {

  state: (): UserInfoState => ({
    token: getToken() as string,
    // name: '',
    // avatar: '',
    userinfo: initUserinfo(),
    menuRoutes: []
  }),

  actions: {
    async login(username: string, password: string) {
      try {
        let result = await userinfoApi.login({ username, password })
        // console.log('登录返回的数据', result);

        this.token = result.token;// token 存到store
        setToken(result.token)  // token 存到localStorage
      } catch (error) {
        ElMessage.error('登录失败，请重试')// 提示信息
        return Promise.reject(error)
      }
    },

    async getInfo() {
      try {
        let result = await userinfoApi.info();
        // console.log('获取到的个人信息', result);

        this.userinfo = result;
        // 用于侧边栏展示的,这里先写死,最终需要通过个人信息返回的权限信息进行修改
        // this.menuRoutes = staticRoutes


        // 现在要做权限
        // 在获取用户信息的actions中,根据接口返回的用户信息不同,而展示出来的页面不通
        // this.menuRoutes 用于侧边栏的展示
        // 怎么做?
        // 1. 接口返回的用户信息有当前用户的权限信息
        // 2. 拿着用户返回的权限信息和 路由进行筛选
        // 3. 有在返回的用户数据中
        //      有权限的生成一个新的数组在侧边栏展示
        //      没有权限的过滤掉
        // 注意:
        // 1. 拿着路由进行筛选,并不是每个路由都需要筛选,不涉及业务逻辑的路由是不需要筛选的,例如: Login、404、首页 等
        // 2. 我们现在要把 需要筛选的路由 和 不需要筛选的路由 分开
        //      需要筛选的路由叫: 动态路由
        //      不需要筛选的路由叫: 静态路由
        //      任意路由必须放在所有路由的最后: 任意路由

        
        // filterRoutesHandler方法  ---  这个方法没写,需要我们自己写
        // 功能: 筛选路由
        // 参数:
        //    参数一: 动态路由 - 动态路由就是需要筛选的路由
        //    参数二: 用户信息返回的当前用户可以看到的菜单
        // 返回值:
        //    返回值是筛选完之后的路由数组
        const filterRoutes = filterRoutesHandler(allAsyncRoutes, result.routes); // 筛选过后的路由
        // ---------------------------------
        const allRoutes = staticRoutes.concat(filterRoutes, anyRoute); // 任意路由必须放在所有路由的最后面
        this.menuRoutes = allRoutes;
        // 至此,侧边菜单栏的展示搞定了
        // 此时,仅仅是侧边的展示ok了,路由注册了吗?
        // 在初始化 router 的时候进行路由注册
        // 注册的时候只注册了 staticRoutes 静态路由
        // 静态路由中只有三个: login 404 和 首页,其他的异步路由和任意路由都没有被注册
        // 所以点击侧边菜单栏跳转路由的时候匹配不到页面,所以是白板
        
        // 每个用户应该根据自己角色的不同(获取个人信息返回的权限数据),可以访问的页面是不同的
        // 除了侧边栏以外,就是这个用户可以访问的页面需要进行路由注册
        // 但是注册路由必须等个人信息接口返回数据之后,经过筛选才能注册
        // 每个人可以进入的页面不同
        // 如果所有的路由在初始化router的时候进行了注册,那么所有的页面也就可以通过输入url的方式进入
        // 这是很危险的,例如:
        // 张三是技术总监,它看不到"财务管理",如果"财务管理"的路由注册了,并且张三这个人知道了财务管理的url
        // 张三虽然看不到"财务管理"的侧边栏,但是可以通过输入url的方式访问这个页面
        // 这样张三就访问到了他无权看到的页面
        // 所以需要动态注册路由,根据当前用户可访问的页面注册路由
        
        addRoutes(allRoutes); // 动态注册路由
      } catch (error) {
        ElMessage.error('获取用户信息失败，请重试')// 提示信息
        return Promise.reject(error)
      }
    },
    async logout() {
      try {
        let result = await userinfoApi.logout();
        this.reset();
      } catch (error) {
        ElMessage.error('退出登录，请重试')// 提示信息
        return Promise.reject(error)
      }
    },
    reset() {
      // 调用退出登录接口
      // 删除local中保存的token
      removeToken()
      // 清除store中的token和用户信息
      this.token = ''
      this.userinfo = initUserinfo()

    },


    // 注意：只要登录之后，就可以获取到token
    // login (username: string, password: string) {
    //   return new Promise((resolve, reject) => {
    //     setTimeout(() => {
    //       if (username==='admin' && password==='111111') {
    //         const token = 'token-atguigu'
    //         setToken(token)  // token 存到localStorage
    //         this.token = token // token 存到store
    //         resolve(token)
    //       } else {
    //         reject(new Error('用户名或密码错误!'))
    //         ElMessage.error('用户名或密码错误!')
    //       }
    //     }, 1000)
    //   })
    // },

    // getInfo () {
    //   return new Promise((resolve, reject) => {
    //     setTimeout(() => {
    //       this.name = 'admin'
    //       this.avatar = 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif'


    //       this.menuRoutes = staticRoutes// 用于侧边栏展示，这里先写死，最终需要通过权限修改
    //       resolve({name: this.name, avatar: this.avatar, token: this.token})
    //     }, 1000)
    //   })
    // },

    // reset() {
    //   // 调用退出登录接口
    //   // 删除local中保存的token
    //   removeToken()
    //   // 清除store中的token和用户信息
    //   this.token = ''
    //   this.userinfo.name = ''
    //   this.userinfo.avatar = ''
    // },
  },
});
